package com.htfyun.roobofactory.factorytest;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.htfyun.roobofactory.BaseActivity;
import com.htfyun.roobofactory.R;
import com.htfyun.roobofactory.htfyunUtils.ExecuteCommand;
import com.htfyun.roobofactory.mediaUtils.myrecorder.IRecordListener;
import com.htfyun.roobofactory.mediaUtils.myrecorder.RecorderOperator;
import com.htfyun.roobofactory.mediaUtils.playerutils.MediaPlayerTool;
import com.htfyun.roobofactory.utils.PermissionManager;

import java.io.IOException;
import java.lang.ref.WeakReference;

/**
 * Created by sst on 2018/7/8.
 */

public class MicTestActivity extends BaseActivity implements View.OnClickListener{

    private static final String RECORDER_FILE_PATH = Environment.getExternalStorageDirectory().getPath() + "/test.pcm";

    private TextView txtInfo;
    private TextView txtStatus;
    private Button btnPass;
    private Button btnFail;
    private Button btnRecordAndPlay;

    private Context mContext;

    private AudioManager mAudioManager;
    //先左后右
    private MicInfoAttr micInfoAttr = MicInfoAttr.left;

    private MediaPlayerTool mediaPlayerTool;
    private Handler myHandler;

    private final static int STATE_WANT_RECORD = 0;
    private final static int STATE_WANT_PLAY = STATE_WANT_RECORD + 1;
    private final static int STATE_WANT_CHECK = STATE_WANT_PLAY + 1;

    private int recordState = STATE_WANT_RECORD;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_factorytest_mic);

        mContext = this;

        myHandler = new MyHandler(this);


        txtInfo = (TextView) findViewById(R.id.txtInfo);
        txtStatus = (TextView) findViewById(R.id.txtStatus);
        btnPass = (Button) findViewById(R.id.btnPass);
        btnFail = (Button) findViewById(R.id.btnFail);
        btnRecordAndPlay = (Button) findViewById(R.id.btnRecordAndPlay);

        btnRecordAndPlay.setEnabled(false);
        txtStatus.setVisibility(View.INVISIBLE);

        btnPass.setOnClickListener(this);
        btnFail.setOnClickListener(this);
        btnRecordAndPlay.setOnClickListener(this);

        mediaPlayerTool = MediaPlayerTool.getInstance(this, myHandler);

        mAudioManager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
        int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        Log.d(TAG,"currentVolume: " + currentVolume + " maxVolume: " + maxVolume);
        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,maxVolume,0);
        int currentVolume1 = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        Log.d(TAG,"currentVolume1: " + currentVolume1 + " maxVolume: " + maxVolume);
        executeShellCommand(ShellCommandEnum.set_micboost);

    }

    @Override
    protected void onResume() {
        super.onResume();
        initPermission();
        updateBtnUI(recordState);

    }

    @Override
    protected void onPause() {
        super.onPause();

        if (!(ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {

            stopRecord();
            stopPlay();

        }
    }

    private void initPermission() {

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

            //同时申请多个权限
            PermissionManager.getInstance(getApplicationContext()).execute(this,
                    Manifest.permission.RECORD_AUDIO,
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE

            );

        } else {

            btnRecordAndPlay.setEnabled(true);
            setRecordingListenerAfterPermissionGranted();

        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionManager.getInstance(getApplicationContext()).
                onRequestPermissionsResult(requestCode, permissions, grantResults);

        Log.e(TAG, "mic ~~~~~~~~~~~~~~onRequestPermissionsResult");

        btnRecordAndPlay.setEnabled(true);
        setRecordingListenerAfterPermissionGranted();

    }

    private void updateBtnUI(int state) {

        if (state == STATE_WANT_RECORD) {

            setBtnPassFailGone(true);
            btnRecordAndPlay.setText(R.string.mic_record);

            txtStatus.setVisibility(View.INVISIBLE);

        } else if (state == STATE_WANT_PLAY) {

            setBtnPassFailGone(true);
            btnRecordAndPlay.setText(R.string.mic_play);

            txtStatus.setVisibility(View.VISIBLE);
            txtStatus.setText(R.string.mic_status_recording);


        } else if (state == STATE_WANT_CHECK) {

            setBtnPassFailGone(false);
            txtStatus.setVisibility(View.VISIBLE);
            txtStatus.setText(R.string.mic_status_playing);

        }

        txtInfo.setText(micInfoAttr.getInfoResId());
        btnPass.setText(micInfoAttr.getPassResId());
        btnFail.setText(micInfoAttr.getFailResId());
    }

    private void setBtnPassFailGone(boolean gone) {
//        btnPass.setVisibility(gone ? View.INVISIBLE : View.VISIBLE);
//        btnFail.setVisibility(gone ? View.INVISIBLE : View.VISIBLE);
        btnPass.setEnabled(!gone);
        btnFail.setEnabled(!gone);
        btnRecordAndPlay.setVisibility(gone ? View.VISIBLE : View.INVISIBLE);

    }

    private void setRecordingListenerAfterPermissionGranted() {


        //设置录音监听器
        RecorderOperator.getInstance().setRecordingListener(new IRecordListener() {

            @Override
            public void onRecordingStop() {
                // TODO Auto-generated method stub
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        Toast.makeText(mContext, R.string.record_stop, Toast.LENGTH_SHORT).show();
                    }
                });
            }

            @Override
            public void onRecordingStart() {
                // TODO Auto-generated method stub

                executeShellCommand(ShellCommandEnum.set_output);

                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        Toast.makeText(mContext, R.string.record_start, Toast.LENGTH_SHORT).show();
                    }
                });
            }

            @Override
            public void onRecordingData(byte[] audiodata) {
                // TODO Auto-generated method stub
//                Log.e(TAG, "录音数据长度："+ audiodata.length);
                //可以在这里将录音数据写入到sdk中

                //https://blog.csdn.net/timsley/article/details/50682992 左右声道存储格式.
                switch (micInfoAttr) {
                    case right:
                        for (int i = 0; i < audiodata.length / 2; i++) {
                            if ((i % 2) == 0) {
                                audiodata[ 2 * i ] = 0;
                                audiodata[ 2 * i + 1] = 0;
                            }
                        }
                        break;
                    case left:
                        for (int i = 0; i < audiodata.length / 2; i++) {
                            if ((i % 2) != 0) {
                                audiodata[ 2 * i ] = 0;
                                audiodata[ 2 * i + 1] = 0;
                            }
                        }
                        break;
                        default:break;
                }
            }
        });
    }

    private void startPlay() {

        mediaPlayerTool.playPcm(RECORDER_FILE_PATH);

    }

    private void stopPlay() {
        mediaPlayerTool.stop();
    }

    private void startRecord() {
        new Thread(new Runnable(){
            @Override
            public void run() {
                RecorderOperator.getInstance().setRecordPath(RECORDER_FILE_PATH);
                RecorderOperator.getInstance().startRecord();
            }}).start();
    }

    private void stopRecord() {
        RecorderOperator.getInstance().stopRecord();
    }

    @Override
    public void onClick(View v) {

        if (v == btnRecordAndPlay) {

            recordState++;
            updateBtnUI(recordState);

            if (recordState == STATE_WANT_PLAY) {
                startRecord();
            } else if (recordState == STATE_WANT_CHECK) {
                stopRecord();
                startPlay();
            }


        } else if (v == btnPass) {

            stopRecord();
            stopPlay();

            if (micInfoAttr == MicInfoAttr.left) {

                micInfoAttr = MicInfoAttr.right;

            } else if (micInfoAttr == MicInfoAttr.right) {

                setResult(RESULT_OK);
                ActivityCompat.finishAfterTransition(getActivity());

            }

            recordState = STATE_WANT_RECORD;
            updateBtnUI(recordState);

        } else if (v == btnFail) {

            setResult(RESULT_CANCELED);
            ActivityCompat.finishAfterTransition(getActivity());

            Log.e(TAG, "btnFail");
        }
    }

    private static class MyHandler extends Handler{
        private final WeakReference<MicTestActivity> reference;

        public MyHandler(MicTestActivity activity) {
            reference = new WeakReference<MicTestActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            MicTestActivity activity = reference.get();
            if (activity == null) {
                return;
            }
            if (msg.what == MediaPlayerTool.EVENT_PLAY_OVER) {
                activity.txtStatus.setText(R.string.mic_status_playing_stop);
            }
        }
    }

    private void executeShellCommand(ShellCommandEnum shellCommandEnum) {
        try {

            ExecuteCommand.execCommand(shellCommandEnum.getCmd());

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    private enum ShellCommandEnum {

        set_micboost("system/bin/cxdish_normal set-micboost 48"),
        set_output("system/bin/cxdish_normal set-output 1,4"),

        ;
        private final String cmd;

        ShellCommandEnum(String cmd) {
            this.cmd = cmd;
        }

        public String getCmd() {
            return cmd;
        }
    }

    private enum MicInfoAttr {
        left(R.string.mic_info_left, R.string.mic_result_left_pass, R.string.mic_result_left_fail),
        right(R.string.mic_info_right, R.string.mic_result_right_pass, R.string.mic_result_right_fail),
        ;

        private final int infoResId;
        private final int passResId;
        private final int failResId;

        MicInfoAttr(int infoResId, int passResId, int failResId) {
            this.infoResId = infoResId;
            this.passResId = passResId;
            this.failResId = failResId;
        }

        public int getInfoResId() {
            return infoResId;
        }

        public int getPassResId() {
            return passResId;
        }

        public int getFailResId() {
            return failResId;
        }
    }


}
